﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine.Dtd.Schema;
using Engine.Sgml.Configuration;
using System.Diagnostics;

namespace Engine.Sgml.Parser {
    internal sealed class Context {

        public Context(ValidatorBehavior behavior, DtdSchema schema, TraceSource traceSource) {
            Guard.ArgumentNotNull(behavior, "behavior");
            Guard.ArgumentNotNull(schema, "schema");
            Guard.ArgumentNotNull(traceSource, "traceSource");

            this.Behavior = behavior;
            this.Schema = schema;
            this.TraceSource = traceSource;
            this.NameReader = new NameReader();
            this.EntityResolver = new EntityResolver(schema);
            this.Readers = new Dictionary<SgmlNodeType, IElementReader>();

            StringBuilder builder = new StringBuilder();
            AttributeReader attributeReader = new AttributeReader(builder);
            ElementReader elementReader = new ElementReader(attributeReader);
            Readers.Add(SgmlNodeType.Element, elementReader);
            Readers.Add(SgmlNodeType.EndElement, elementReader);
            Readers.Add(SgmlNodeType.Attribute, attributeReader);
            Readers.Add(SgmlNodeType.DocumentType, new DoctypeReader(attributeReader, builder));
            Readers.Add(SgmlNodeType.Comment, new CommentReader());
            Readers.Add(SgmlNodeType.ProcessingInstruction, new PInstructionReader());
            Readers.Add(SgmlNodeType.WhiteSpace, new WhiteSpaceReader(builder));
            Readers.Add(SgmlNodeType.CDataSection, new CDataSectionReader());
            Readers.Add(SgmlNodeType.Text, new ParsedCDataReader(builder));
            Readers.Add(SgmlNodeType.CData, new CDataReader(builder));
            }

        public int LineNumber { get; private set; }
        public int LinePosition { get; private set; }

        public ValidatorBehavior Behavior { get; private set; }
        public DtdSchema Schema { get; internal set; }
        public NameReader NameReader { get; private set; }
        public EntityResolver EntityResolver { get; private set; }
        public IDictionary<SgmlNodeType, IElementReader> Readers { get; private set; }
        public TraceSource TraceSource { get; private set; }

        internal void SetLineInfo(SgmlStreamReader reader) {
            Debug.Assert(reader != null);
            LineNumber = reader.LineNumber;
            LinePosition = reader.LinePosition;
            }
        }
    }
